<#
.SYNOPSIS
	Used to get information about the disks in a filer
.DESCRIPTION
	Get disk status information from RAID. Only disks owned by the filer or its 
	partner are eligible for inclusion in the returned list..
.PARAMETER Disk
  	Name of the disk example 'v0.20'
.PARAMETER Server
   	NaServer to query
.EXAMPLE
  	#Get all spares in a filer. 
  	PS > Get-NaDisk -spares
.EXAMPLE
   	#Get the status of disk "v2.22" from filer "toaster".
	PS > $NaServer = New-NaServer -server "Toaster"
	PS > Get-NaDisk -disk "v2.22" -Server $NaServer
.OUTPUTS
	NetApp.SDK.NaDisk[]
.Link
	Set-NaDisk
#> 
function Get-NaDisk {
	[CmdletBinding(SupportsShouldProcess=$FALSE,SupportsTransactions=$False,ConfirmImpact="None",DefaultParameterSetName="")]
	param(
		[Parameter(Position=0,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the disk example 'v0.20'")]
		[Alias("Disk")]
		[string]
		$Name,
			
		[Parameter()]
		[switch]
		$spares,
		
		[Parameter(Position=1,HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer]
		$server = (Get-NaServer)
	)
	Begin {
		$out = @()
	}
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("disk-list-info")
		if ($Name){
			$request.AddNewChild("disk",$Name)
		}
		try {
			$result  = ([xml]$server.InvokeElem($request)).results
		}
		catch [NetApp.Manage.NaApiFailedException]{
			Write-Warning $_.Exception.GetBaseException().message
			$result = $null
			continue;
		}
		if ($?){
			$result."disk-details"."disk-detail-info" |% {
				$out += New-Object NetApp.SDK.NaDisk -ArgumentList @(
					$_."aggregate",
					$_."bay",
					$_."blocks-Read",
					$_."blocks-Written",
					$_."broken-details",
					$_."bytes-Per-Sector",
					$_."checksum-Compatibility",
					$_."copy-Destination",
					$_."copy-Percent",
					$_."disk-Model",
					$_."disk-Type",
					$_."disk-Uid",
					$_."effective-Disk-Type",
					$_."firmware-Revision",
					$_."grown-Defect-List-Count",
					$_."host-Adapter",
					$_."id",
					(ConvertFrom-NaBool $_."is-dynamically-Qualified"),
					(ConvertFrom-NaBool $_."is-offline"),
					(ConvertFrom-NaBool $_."is-prefailed"),
					(ConvertFrom-NaBool $_."is-replacing"),
					(ConvertFrom-NaBool $_."is-zeroed"),
					$_."name",
					$_."physical-Blocks",
					$_."physical-Space",
					$_."pool",
					$_."plex",
					$_."port",
					$_."port-Name",
					$_."power-On-Hours",
					$_."raid-group",
					$_."raid-State",
					$_."raid-Type",
					$_."raw-Disk-Sectors",
					$_."reconstruction-Percent",
					$_."rpm",
					$_."scrubCount",
					$_."scrubLast-Done",
					$_."secondary-Name",
					$_."secondary-Port",
					$_."serial-Number",
					$_."shelf",
					$_."shm-Time-Interval",
					$_."used-Blocks",
					$_."used-Space",
					($_."v-series-detail-info"."v-series-detail-info" | % {
						New-Object NetApp.SDK.NaVSeries -ArgumentList @(
							$_."product-id",
							$_."primary-array-port-wwn",
							$_."primary-array-switch-port-wwn",
							$_."primary-controller-port-wwn",
							$_."primary-lun-number",
							$_."primary-switch-name",
							$_."primary-switch-port",
							$_."alternate-array-port-wwn",
							$_."alternate-array-switch-port-wwn",
							$_."alternate-controller-port-wwn",
							$_."alternate-lun-number",
							$_."alternate-switch-name",
							$_."alternate-switch-port"
						)}
					),
					$_."vendor-Id",
					$_."volume",
					$_."zeroing-Percent"
				)
			}
		}
	}
	end {
		if ($spares) {
			return $out | ? {$_.raidstate -eq "spare"}
		} else {
			return $out
		}
	}
}

Function Set-NaDisk {
	<#
	.Synopsis
       	Used to Set the physical state of a disk
    .Description
       	Used to Set the physical state of a disk
    .Parameter Disk
      	Name of the disk example 'v0.20'
	.Parameter Fail
      	Fail a file system disk. Removes the specified file system disk from 
	  	the RAID configuration, spinning the disk down when removal is complete.
    .Parameter FailNow
      	Fail the specified disk immediately, the disk will not be spun down
    .Parameter Remove
      	Remove a spare disk. Removes the specified spare disk from the RAID configuration, 
	  	spinning the disk down when removal is complete.
	.Parameter Replace
      	Initiate replacing a file system disk with an appropriate spare disk.
	.Parameter ReplacementDisk
      	Name of the spare disk to use as a replacement. 
	.Parameter Force
      	Allow replacement-disk to come from the opposite spare pool. 
	  	Also allow replacement disk not matching rotational speed of majority of 
	  	disks in the aggregate
	.Parameter CancelReplace
      	Abort disk replace operation.
	.Parameter UnFail
      	Unfail a disk in the broken pool, by clearing its FDR (Failed Disk Registry) 
	  	entry and unfailing it at the Storage Layer.
	.Parameter MakeSpare
      	Force the disk to become a spare upon unfail
	.Parameter Server
       	NaServer to query
    .Example
       	# Fail a disk by default fail will safley remove a drive.  
       	PS > Get-NaDisk -Disk v0.20 | Set-NaDisk -Fail
	.Example
       	# if more imediate action is required -FailNow will force an instantantious result! 
       	PS > Set-NaDisk -disk (Get-NaDisk -disk v0.20) -Fail -FailNOW
	.Example
       	# Unfail will mark a failed disk as good and return it to the pool 
       	PS > Set-NaDisk -disk (Get-NaDisk -disk v0.20) -UnFail
	.Example
       	#  Unfail will mark a failed disk as good and return it to the pool. The -MakeSpare 
	   	#  switch will also mark that drive as a non-zeroed spare.  
       	PS > Set-NaDisk -disk "v0.20" -UnFail -MakeSpare
	.Example
       	#  Prepair a drive for removal from the system. 
        PS > Get-NaDisk -Disk v0.20 | Set-NaDisk -remove
	.Example
       	#  Live migrate from one drive to another.  -replace requires two disks
	   	#  be specified.  
	   	#  	-replace Target disk -> the one being replaced.
		#	-ReplacementDisk The spare that will replace your target.
		PS > $Spare = Get-nadisk -spare |?{$_.RPM -eq 15000}|select -First 1
	   	PS > Get-NaDisk -disk v0.20 | Set-NaDisk -ReplacementDisk $Spare.disk
	.Outputs
    	NetApp.SDK.NaDisk[]
    .Link
    	Get-NaDisk
	#> 
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param(
		[Parameter(Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,ParameterSetName="ReplaceDisk",HelpMessage="Name of the disk example 'v0.20'")]
        [Parameter(Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,ParameterSetName="AbortReplaceDisk",HelpMessage="Name of the disk example 'v0.20'")]
        [Parameter(Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,ParameterSetName="Faildisk",HelpMessage="Name of the disk example 'v0.20'")]
        [Parameter(Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,ParameterSetName="unFaildisk",HelpMessage="Name of the disk example 'v0.20'")]
        [Parameter(Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,ParameterSetName="RemoveDisk",HelpMessage="Name of the disk example 'v0.20'")]
		[Alias("Disk")]
		[string]
		$Name,
		
		[Parameter(ParameterSetName="Faildisk")]
		[switch]
		$Fail,
		
		[Parameter(ParameterSetName="Faildisk")]
		[switch]
		$FailNow,
		
		[Parameter(ParameterSetName="RemoveDisk")]
		[switch]
		$Remove,
		
		[Parameter(ParameterSetName="ReplaceDisk")]
		[switch]
		$Replace,
		
		[Parameter(Mandatory=$TRUE,Position=1,ParameterSetName="ReplaceDisk")]
		[string]
		$ReplacementDisk,
		
		[Parameter(ParameterSetName="ReplaceDisk")]
		[switch]
		$Force,
		
		[Parameter(ParameterSetName="AbortReplaceDisk")]
		[switch]
		$CancelReplace,
	
		[Parameter(ParameterSetName="unFaildisk")]
		[switch]
		$UnFail,
		
		[Parameter(ParameterSetName="unFaildisk")]
		[switch]
		$MakeSpare,
		
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer]
		$server = (Get-NaServer)
	)
	Process {
        switch ($pscmdlet.ParametersetName) {
            "Faildisk"         
            {
            	$request = New-Object Netapp.Manage.NaElement -ArgumentList @("disk-fail")
    			$request.AddNewChild("disk",$name)
    			$msg = "Fail Disk $Name"
    			if ($FailNow){
    				$request.AddNewChild("is-immediate",$TRUE)
    				$msg += " Immediaty"
    			}
            
            }
            "unFaildisk"
            {
                $request = New-Object Netapp.Manage.NaElement -ArgumentList @("disk-unfail")
    			$request.AddNewChild("disk",$Name)
    			$msg = "Unfail Disk $Name"
    			if ($MakeSpare){
    				$request.AddNewChild("make-spare",$TRUE)
    				$msg += " and make spare"
    			}
            }
            "RemoveDisk"
            {
                $request = New-Object Netapp.Manage.NaElement -ArgumentList @("disk-remove")
    			$request.AddNewChild("disk",$Name)
    			$msg = "Remove Disk $Name"
            }
            "ReplaceDisk"
            {
                $request = New-Object Netapp.Manage.NaElement -ArgumentList @("disk-replace-start")
    			$request.AddNewChild("disk",$Name)
    			if ($ReplacementDisk){
    				$request.AddNewChild("replacement-disk",$ReplacementDisk)
    				$msg = "Replace $Name with $ReplacementDisk "
    			}
    			else{ 
    				Throw " If -replace is specified, then -ReplacementDisk <[string]> must also be supplied. "
    			}
    			if ($Force){
    				$request.AddNewChild("force",$TRUE)
    			}
            }
            "AbortReplaceDisk" 
            {
                $request = New-Object Netapp.Manage.NaElement -ArgumentList @("disk-replace-stop")
    			$request.AddNewChild("disk",$Name)
    			$msg = "Cancel Disk Replace $Name"
            }
        }
		if ($pscmdlet.ShouldProcess($Server.Server, $Msg)){
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
			if ($?){
				return Get-NaDisk -disk $Name -Server $server
			}
        }
	}
}

Function Add-NaDisk {
	<#
	.Synopsis
   		Add disks to the specified aggregate.
	.Description
   		Add disks to the specified aggregate, whether it is free-standing or embedded
 		in a traditional volume. The disks to add are specified in the same way as for
 		Add-NaAggr. Disks cannot be added to a mirrored aggregate if one or more of the
 		plexes is offline. By the time the API returns, the disk(s) may not yet be 
		completely added. Use Get-NaAggr to query the aggregate status to determine
 		when it has finished growing due to the added disk(s).
	.Parameter Name
   		Name of the aggregate to which the disks will be added. 
	.Parameter DiskCount
   		Number of disks to add, including the parity disks. The disks will come from the pool
 		of spare disks. The smallest disks in this pool join the aggregate first, unless the 
 		-DiskSize argument is specified. Either the -DiskSize or -Disk argument must be specified.
	.Parameter DiskSize
   		The disk size in GB. Disks that are within approximately 20% of the specified size will 
 		be selected for use in the aggregate. if not specified, existing groups are appended with
 		disks that are the best match for the largest disk in the group. When starting new groups,
 		the smallest disks are selected first. 
	.Parameter Disk
   		Specific list of disks to add to the aggregate. If the aggregate is mirrored and a specific
 		list of disks is supplied, another list -MirrorDisks must also be supplied with the same 
 		number of disks.
	.Parameter RaidGroup
   		Specifies the RAID group (for example rg0) to which the indicated disks are to be added. 
 		When a RAID group other than the last RAID group is specified, the aggregate can no longer
 		be reverted to a version of ONTAP prior to 6.2. in such a case, the -ForceSparePool switch
 		must be specified as well. By default, the filer fills up one RAID group with disks before
 		starting another RAID group. Suppose an aggregate currently has one RAID group of 12 disks
 		and its RAID group size is 14. if you add 5 disks to this aggregate, it will have one RAID
 		group with 14 disks and another RAID group with 3 disks. The filer does not evenly 
 		distribute disks among RAID groups. 
	.Parameter Force
   		Disks in a plex are not normally permitted to span spare pools. This behavior is overridden
 		when this option is specified. 
	.Parameter GroupSelectionMode
   		Specifies how DATA ONTAP adds the specified disks to raidgroups. Legitimate values are "last",
 		"one", "new" or "all". -GroupSelectionMode is an optional argument, and the behavior when it
 		is not used is selected by value of -RaidGroup. if -raidgroup is used, the behavior is the same
 		as for -GroupSelectionMode "one". if -RaidGroup is not used, the behavior is the same as for 
 		-GroupSelectionMode "last". The -RaidGroup option must be used with -GroupSelectionMode value
 		"one", and it cannnot be used with others. if the string value is "last", Data ONTAP adds the 
 		specified disks to the existing last RAID group first. After the last RAID group is full, it 
 		creates one or more new RAID groups and adds the remaining disks to the new groups. if the string
 		value is "one", Data ONTAP adds the specified disks to the existing RAID group specified by 
 		raid-group option until this specified RAID group is full. if the string value is "new", Data 
 		ONTAP creates one or more new RAID groups and adds the specified disks to the new groups, even 
 		if they would fit into an existing RAID group. The name of new RAID groups are selected automatically.
 		It is not possible to specify the name for the new RAID groups. if the string value is "all", Data 
 		ONTAP adds the specified disks to existing RAID groups first. Only after all existing RAID groups 
 		are full, it creates one or more new RAID groups and adds the remaining disks to the new groups. 
	.Parameter MirrorDisks
   		Specific list of mirror disks needed to accompany the list in the -Disk parameter. This list must
 		contain the same number of disks as specified in -Disk. 
	.Parameter Server
		NaServer to query
	.Example
		# Add four disks to aggr1
   		PS > Get-NaAggr aggr1 | Add-NaAggr -DiskCount 4
	.Example
		# Add 8 disks to Aggr1 RG0
 		PS > Get-NaAggr aggr1 | Add-NaAggr -DiskCount 8 -RaidGroup RG0
	.Example
		Add disks from shelf 4 to the mirrored Aggregate Aggr3, and add the disks from shelf 5 to aggr3 mirror.
		Create a new rg with the specified disks
 	
		PS > $disks = Get-NaDisk -spare | ? {$_.shelf -eq 4}| Select -ExpandProperty Disk
 		PS > $Mirrordisk = Get-NaDisk -spare | ? {$_.shelf -eq 5}| Select -ExpandProperty Disk
		PS > Add-NaDisk -Name Aggr3 -Disk $disks -MirrorDisks $Mirrordisk -GroupSelectionMode "new"
	.Outputs
    	NetApp.SDK.NaAggr[]
    .Link
    	Get-NaAggr
    	New-NaAggr
	#>
	[CmdletBinding(SupportsShouldProcess=$true,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="Diskcount")]
	param(
		[Parameter(Position=0,Mandatory=$TRUE,ParameterSetName="Diskcount",ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the aggregate to which the disks will be added.")]
        [Parameter(Position=0,Mandatory=$TRUE,ParameterSetName="Disklist",ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the aggregate to which the disks will be added.")]
        [Parameter(Position=0,Mandatory=$TRUE,ParameterSetName="MirrorDisklist",ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the aggregate to which the disks will be added.")]
		[Alias("Aggregate")]
		[STRING]
		$Name,
	
		[Parameter(Position=1,Mandatory=$TRUE,ParameterSetName="Diskcount",HelpMessage="Number of disks to add, including the parity disks.")]
		[INT]
		$DiskCount,
	
		[Parameter(ParameterSetName="Diskcount",HelpMessage="The disk size in GB.")]
		[INT]
		$DiskSize,
	
        [Parameter(Mandatory=$TRUE,ParameterSetName="Disklist",HelpMessage="Specific list of disks to use for the new aggregate.")]
		[Parameter(Mandatory=$TRUE,ParameterSetName="MirrorDisklist",HelpMessage="Specific list of disks to use for the new aggregate.")]
		[string[]]
		$Disk,
	
		[Parameter(Mandatory=$TRUE,ParameterSetName="MirrorDisklist",HelpMessage="List of mirror disks to use. It must contain the same number of disks specified in -disks")]
		[string[]]
		$MirrorDisks,
	
		[Parameter(HelpMessage="Specifies how DATA ONTAP adds the specified disks to raidgroups. Legitimate values are last, one, new or all.")]
		[ValidateSet("last", "one", "new","all")]
		[STRING]
		$GroupSelectionMode,
	
		[Parameter(HelpMessage="Specifies the RAID group (for example rg0) to which the indicated disks are to be added.")]
		[STRING]
		$RaidGroup,
        
        [Parameter()]
		[switch]
		$Force,
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	Process{
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("aggr-add")
		$request.AddNewChild("aggregate",$name)   
        switch ($PSCmdlet.ParametersetName) {
            "Diskcount"
            {
                $request.AddNewChild("disk-count",$DiskCount)
    			$msg = "Adding $diskCount disks to $Name"
                if ($DiskSize){
        			$request.AddNewChild("disk-size",$DiskSize)
        		}
            }
            "Disklist"
            {
                $d = New-Object Netapp.Manage.NaElement("disks")
    			foreach ($_d in $Disk){
                    $di = New-Object Netapp.Manage.NaElement("disk-info")
                    $di.AddNewChild("name",$_d.disk)
                    $d.AddChildElement($di)
                }
                $request.AddChildElement($d)
            }
            "MirrorDisklist"
            {
                $d = New-Object Netapp.Manage.NaElement("disks")
    			foreach ($_d in $Disk){
                    $di = New-Object Netapp.Manage.NaElement("disk-info")
                    $di.AddNewChild("name",$_d)
                    $d.AddChildElement($di)
                }
                $request.AddChildElement($d)
                $m = New-Object Netapp.Manage.NaElement("mirror-disks")
       			foreach ($_d in $MirrorDisks){
                    $mi = New-Object Netapp.Manage.NaElement("disk-info")
                    $mi.AddNewChild("name",$_d)
                    $m.AddChildElement($mi)
                }
                $request.AddChildElement($m)
            }
        }
		if ($Force){
			$request.AddNewChild("force-spare-pool",$TRUE)
		}
		if ($GroupSelectionMode){
			$request.AddNewChild("group-selection-mode",$GroupSelectionMode)
		}
		if ($RaidGroup){
			$request.AddNewChild("raid-group",$RaidGroup)
		}
		if ($pscmdlet.ShouldProcess($Server.Server,$msg)){
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
			if ($?){
				$pscmdlet.WriteVerbose("Disks added!")
				return Get-NaAggr -name $name -Server $Server
			}
		}
	}
}

Function Start-NaDiskSwap {
	<#
	.Synopsis
    	Prepare (quiet) bus for swap. Applies to SCSI disks only.
    .Description
        Prepare (quiet) bus for swap. Applies to SCSI disks only. It stalls all I/O on the filer
	    to allow a disk to be physically added or removed from a disk shelf. Typically, this 
	    command would be used to allow removal of a failed disk, or of a file system or spare 
	    disk that was prepared for removal using the disk fail or disk remove command. Once a disk
	    is physically added or removed from a disk shelf, system I/O will automatically continue. 
	
	    NOTE: It is important to issue the disk swap command only when you have a disk that you 
	    want to physically remove or add to a disk shelf, because all I/O will stall until a disk
	    is added or removed from the shelf.
	.Parameter Server
        NaServer to query
	.Example
        # Prepair a scsi bus for disk swap
        PS > Start-NADiskSwap
    .Link
    	Stop-NaDiskSwap
	#> 
	[CmdletBinding(SupportsShouldProcess=$TRUE,SupportsTransactions=$False,ConfirmImpact="None",DefaultParameterSetName="")]
	param(
		[Parameter(Position=0,HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer]
		$server = (Get-NaServer)
	)
	Process {
		if ($pscmdlet.ShouldProcess($Server.Server,"Stoping ALL I/O")){
            try {
				$server.Invoke("disk-swap")|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
	    }
    }
}

function Stop-NaDiskSwap {
	<#
	.Synopsis
    	Undo disk swap and resume service.
    .Description
        Undo disk swap and resume service.
	.Parameter Server
       	NaServer to query
	.Example
      	# Stops a Disk swap and resumes all I/O on SCSI bus.
       	PS > Stop-NADiskSwap
    .Link
    	Start-NaDiskSwap
	#> 
	[CmdletBinding(SupportsShouldProcess=$TRUE,SupportsTransactions=$False,ConfirmImpact="None",DefaultParameterSetName="")]
	param(
		[Parameter(Position=0,HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer]
		$server = (Get-NaServer)
	)
	Process{
		if ($pscmdlet.ShouldProcess($Server.Server, "Resuming service")){
			try {
				$server.Invoke("disk-unswap") | out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
	    }
	}
}

function Start-NaZeroSpares {
	<#
	.Synopsis
        Set up all non-zeroed spares owned by the filer to start zeroing.
    .Description
        Set up all non-zeroed spares owned by the filer to start zeroing. This operation
	 	is asynchronous, and therefore returns no errors that might occur when the zeroing
	 	operation actually starts, which could be several seconds after this API operation
	 	completes. Zeroing progress can be monitored via the Get-NaDisk Cmdlet. 
	 	The ZeroingPercent Property is returned if disk zeroing has started, and the Zeroed
	 	returns TRUE once the zeroing has completed (or, if zeroing wasn't necessary in the first place).
	.Parameter Server
        NaServer to query
	.Example
        # Zero All spares
        Start-NaZeroSpares
	#> 
	[CmdletBinding(SupportsShouldProcess=$TRUE,SupportsTransactions=$False,ConfirmImpact="None",DefaultParameterSetName="")]
	param(
		[Parameter(Position=0,HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer]
		$server = (Get-NaServer)
	)
	Process {
		if ($pscmdlet.ShouldProcess($Server.Server, "Zero All Spares")){
			$server.Invoke("disk-zero-spares") | out-null
		}
    }
}

function Update-NaDiskFirmware {
	<#
	.Synopsis
        Start disk firmware download process to update firmware on disks.
    .Description
        Start disk firmware download process to update firmware on disks. This operation
	 	is asynchronous, and therefore returns no errors that might occur during the 
	 	download process. This operation will only update firmware on disks that do not 
	 	have the latest firmware revision. The firmware revision on the disk can be 
	 	monitored via the Get-NaDisk Cmdlet.
	.Parameter Disk
        Name of the disk example 'v0.20'
	.Parameter Server
        NaServer to query
    .Example
        # Update the firmware on all disks
        PS > Start-NaZeroSpares
    .Example
        # Update the firmware on a disk.
        PS > Update-NaDiskFirmware -name 'v1.20'
    .Example
    	# update any disks model VD-100MB where the firmware isnot 0042
    	PS > Get-NaDisk | ?{$_.Model -eq 'VD-100MB' -and $_.Firmware -ne '0042'} | Update-NaDiskFirmware
	#> 
	[CmdletBinding(SupportsShouldProcess=$TRUE,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param(
		[Parameter(Position=0,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the disk example 'v0.20'")]
		[Alias("Disk")]
		[string[]]
		$Name,
		
		[Parameter(Position=1,HelpMessage="[NAServer]NAserver (New-NAServer)")]
		[NetApp.SDK.NaServer]
		$server = (Get-NaServer)
	)
	Process {
		$target = 'All Spares'
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("disk-update-disk-fw")
		if ($Name){
            $d = New-Object Netapp.Manage.NaElement("disk-list")
            foreach ($n in $name){
                $d.AddNewChild("disk-name", $n)
            }
            $request.AddChildElement($d)
		}
		if ($pscmdlet.ShouldProcess($Server.Server,"Starting firmware download"))
        {
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
	  	} 
  	}
}
